home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CUCD / Magazine / C_Tutorial / Part-10 / frac1 / fractal.c < prev    next >
C/C++ Source or Header  |  1998-03-02  |  3KB  |  109 lines

  1. #include "fractal.h"
  2.  
  3. #include<exec/tasks.h>
  4.  
  5. #include<stdlib.h>
  6. #include<stdio.h>
  7.  
  8. #include "gadgets.h"
  9.  
  10. #include<clib/alib_protos.h>
  11. #include<clib/exec_protos.h>
  12. #include<clib/graphics_protos.h>
  13.  
  14. static int calc(double, double, int);
  15. static void fractal(void);
  16.  
  17. /* The mechanism by which we will control our task: */
  18. /* One Semaphore for drawing, the other for running */
  19. static SignalSemaphore drawing;
  20. static SignalSemaphore running;
  21.  
  22. /* Initialisation done when program is started */
  23. void initSemaphores()
  24. {
  25.     InitSemaphore(&drawing);
  26.     InitSemaphore(&running);
  27. }
  28.  
  29. /* To stop the fractal we stop it drawing then stop our */
  30. /* task from running */
  31. void stopFractal()
  32. {
  33.     ObtainSemaphore(&drawing);
  34.     ObtainSemaphore(&running);
  35.     ReleaseSemaphore(&running);
  36.     ReleaseSemaphore(&drawing);
  37. }
  38.  
  39. /* A local copy of the window pointer for our task */
  40. static struct Window* win;
  41.  
  42. /* Draw a fractal in the window */
  43. void drawFractal(struct Window* w)
  44. {
  45.     /* If the semaphore is available a task is not already running */
  46.     if(AttemptSemaphore(&running))
  47.     {
  48.         struct Task* task;
  49.         ReleaseSemaphore(&running);
  50.         /* Make a copy of the window pointer for the task to use */
  51.         win = w;
  52.         /* Create a new task which will draw the fractal */
  53.         task = CreateTask("HelloPainter-Fractal",-1,&fractal,4096);
  54.         if(task == NULL)
  55.             printf("Error: could not create task\n");
  56.     }
  57.     else
  58.         /* The semaphore was already taken, so stop the task */
  59.         stopFractal();
  60. }
  61.  
  62. /* The starting point of our task */
  63. static void __saveds fractal()
  64. {
  65.     /* If the semaphore is available we can start running */
  66.   if(AttemptSemaphore(&running))
  67.   {
  68.         /* The width, height and number of colours for drawing */
  69.         int w=win->Width, h=win->Height, d=1<<win->WScreen->BitMap.Depth;
  70.         /* The snapshot of the mandelbrot set to draw */
  71.         /* (Adjust these numbers to draw different fractals) */
  72.         double width=4.0, height=4.0, top=-2.0, left=-2.5;
  73.         int x;
  74.         /* Check whether we can continue drawing on each x */
  75.         for(x=0; x<w && AttemptSemaphore(&drawing); x++)
  76.         {
  77.             int y;
  78.             for(y=0; y<h; y++)
  79.             {
  80.                 /* Set the current colour */
  81.                 setFgPen(win, calc(x*width/w+left,y*height/h+top,d));
  82.                 /* Draw the pixel */
  83.                 WritePixel(win->RPort,x,y);
  84.             }
  85.             /* Release the semaphore before checking again */
  86.             ReleaseSemaphore(&drawing);
  87.         }
  88.         /* Release the semaphore to indicate the task has finished */
  89.         ReleaseSemaphore(&running);
  90.     }
  91. }
  92.  
  93. /* Calculate the colour of a particular point */
  94. /* (This is the number of iterations of the equation */
  95. /* needed to exceed the bound value) */
  96. static int calc(double x, double y, int d)
  97. {
  98.     double xc=x, yc=y;
  99.     int it;
  100.     /* Adjust the 16.0 to give different colour spreads */
  101.     for(it=0; it<d && (xc*xc)+(yc*yc)<16.0; it++)
  102.     {
  103.         double oldx = xc;
  104.         xc = oldx*oldx-yc*yc+x;
  105.         yc = 2.0*oldx*yc+y;
  106.     }
  107.     return it;
  108. }
  109.